"""
Case Type   : GUC
Case Name   : 使用gs_guc set方法在备机设置参数primary_slotname,观察预期结果
Create At   : 2020/12/2
Owner       : zhanghuan96
Description :
        1.修改wal_level为logical
        2.查询修改后的参数值
        3.主机上创建逻辑复制槽
        4.备机修改primary_slotname参数值
        5.查询集群状态
        6.备机删除primary_slotname参数
        7.恢复环境
Expect      :
        1.成功
        2.成功
        3.成功
        4.成功
        5.备机为need repair
        6.成功
        7.成功
History     :modified by zhanghuan96，2022.05.17，优化重建备机
"""
import os
import re
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro

Pri_SH = CommonSH('PrimaryDbUser')
constant = Constant()


@unittest.skipIf(1 == Pri_SH.get_node_num(), '单机环境不执行')
class HAReplication(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.primary_node = Node('PrimaryDbUser')
        self.standby_node = Node('Standby1DbUser')
        self.standby_sh = CommonSH('Standby1DbUser')
        self.com = Common()
        self.Standby1_Root_Node = Node('Standby1Root')
        self.pg_conf = os.path.join(macro.DB_INSTANCE_PATH, 'postgresql.conf')
        self.node_num = Pri_SH.get_node_num()
        self.default_value = self.com.show_param('wal_level')
        self.slot_name = "s_replication0055"

    def test_primary_slotname(self):
        text = '--step1:修改wal_level为logical;expect:成功--'
        self.log.info(text)
        mod_msg = Pri_SH.execute_gsguc('set',
                                       constant.GSGUC_SUCCESS_MSG,
                                       'wal_level =logical')
        self.log.info(mod_msg)
        self.assertTrue(mod_msg)
        restart_msg = Pri_SH.restart_db_cluster()
        self.log.info(restart_msg)
        status = Pri_SH.get_db_cluster_status()
        self.assertTrue("Degraded" in status or "Normal" in status,
                        '执行失败:' + text)

        text = '--step2:查询修改后的参数值;expect:成功--'
        self.log.info(text)
        sql_cmd = Pri_SH.execut_db_sql('show wal_level;')
        self.log.info(sql_cmd)
        self.assertEqual('logical', sql_cmd.split('\n')[2].strip(),
                         '执行失败:' + text)

        text = '--step3:主机上创建逻辑复制槽;expect:成功--'
        self.log.info(text)
        check_res = Pri_SH.execut_db_sql('select slot_name from '
                                         'pg_replication_slots;')
        self.log.info(check_res)
        if f'{self.slot_name}' == check_res.split('\n')[-2].strip():
            del_cmd = Pri_SH.execut_db_sql(f'''select * from \
            pg_drop_replication_slot('{self.slot_name}');
                                 ''')
            self.log.info(del_cmd)
        create_cmd = Pri_SH.execut_db_sql(f'''select * from  \
        pg_create_logical_replication_slot('{self.slot_name}',\
        'mppdb_decoding');''')
        self.log.info(create_cmd)
        self.assertIn(f'{self.slot_name}', create_cmd, '执行失败:' + text)

        text = '--step4:备机修改primary_slotname参数值;expect:成功--'
        self.log.info(text)
        self.log.info('--获取备机hostname--')
        check_cmd = 'hostname'
        self.log.info(check_cmd)
        hostname = self.Standby1_Root_Node.sh(check_cmd).result()
        self.log.info(hostname)
        mod_msg = self.standby_sh.execute_gsguc('set',
                                                constant.GSGUC_SUCCESS_MSG,
                                                f"primary_slotname ="
                                                f"'{self.slot_name}'",
                                                node_name=f'{hostname}')
        self.log.info(mod_msg)
        self.assertTrue(mod_msg)
        restart_msg = self.standby_sh.restart_db_cluster()
        self.log.info(restart_msg)

        text = '--step5:查询集群状态;expect:备机为need repair--'
        self.log.info(text)
        check_status = self.standby_sh.get_db_cluster_status('detail')
        self.log.info(check_status)
        self.assertIn('Standby Need repair', check_status, '执行失败:' + text)

        text = '--step6:备机删除primary_slotname参数;expect:成功--'
        self.log.info(text)
        del_cmd = f"sed -i '/primary_slotname/d' {self.pg_conf}"
        self.log.info(del_cmd)
        msg = self.standby_node.sh(del_cmd).result()
        self.log.info(msg)
        self.assertEqual('', msg, '执行失败:' + text)

    def tearDown(self):
        text = '--step7:恢复环境;expect:成功--'
        self.log.info(text)
        self.log.info('--重建备机--')
        build_msg_list = Pri_SH.get_standby_and_build()
        self.log.info(build_msg_list)
        restart_msg = self.standby_sh.restart_db_cluster()
        self.log.info(restart_msg)
        self.log.info('---检查数据库状态---')
        status = Pri_SH.get_db_cluster_status(param='all')
        self.log.info(status)
        regex_res = re.findall('instance_state.*:.*Normal', status)
        self.log.info(regex_res)
        self.log.info('---删除逻辑复制槽---')
        del_cmd = Pri_SH.execut_db_sql(f"select * from "
                                       f"pg_drop_replication_slot"
                                       f"('{self.slot_name}');")
        self.log.info(del_cmd)
        self.log.info('---恢复参数默认值---')
        restore_cmd = Pri_SH.execute_gsguc('set',
                                           constant.GSGUC_SUCCESS_MSG,
                                           f"wal_level='{self.default_value}'")
        self.log.info(restore_cmd)
        restart_msg = Pri_SH.restart_db_cluster()
        self.log.info(restart_msg)
        status = Pri_SH.get_db_cluster_status()
        self.log.info(status)
        self.assertTrue("Degraded" in status or "Normal" in status)
        self.assertEqual(len(regex_res), self.node_num)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
